﻿using Game.ModbusHepler.Resolve;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using OfficeOpenXml;
using ReactiveChannelMessaging.Communication;
using ReactiveChannelMessaging.Core;
using ReactiveChannelMessaging.Examples;
using ReactiveChannelMessaging.Processors;
﻿﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
// 添加必要的命名空间引用
using System.Threading.Tasks;
using static OfficeOpenXml.ExcelErrorValue;
using static ReactiveChannelMessaging.ModbusHepler.ModbusCommandParser;
using static ReactiveChannelMessaging.WinForms.WaitForResponseHelper;

namespace ReactiveChannelMessaging.WinForms;

/// <summary>
/// 简化的主窗体 - 业务逻辑部分
/// UI创建代码已移至Designer文件
/// </summary>
public partial class SimpleMainForm : Form
{
    #region 字段和属性

    private IHost? _host;
    private ReactiveMessageBus? _messageBus;
    private CommunicationManager? _communicationManager;
    private ILogger<SimpleMainForm>? _logger;

    // 测试相关字段
    private readonly List<string> _testCommands = new List<string> { "01 04 00 26 00 01 D0 01" };
    private CancellationTokenSource? _testCancellationToken;
    private Task? _testTask;
    private Random _random = new Random();
    private DateTime _testStartTime;
    private int _testCount = 0;
    private int _testSuccessCount = 0;
    private int _testFailureCount = 0;
    private bool _isTestRunning = false;
    private readonly ConcurrentDictionary<int, DateTime> _pendingCommands =
        new ConcurrentDictionary<int, DateTime>();
    private readonly object _testLock = new object();
    private int _commandIndex = 0;

    // 添加命令列表的BindingList
    private BindingList<CommandItem> _commandItems = new BindingList<CommandItem>();

    // 订阅管理
    private List<IDisposable>? _subscriptions;
    private volatile bool _isDisposing = false;

    // 日志控制 - 测试时禁用串口日志以提高性能
    private bool _enableSerialLogging = true;
    private Subject<ResponseDataMessage> _dataSubject; // 声明但不初始化

    // 添加用于普通发送操作的响应确认机制
    private readonly ConcurrentDictionary<Guid, PendingRequest> _pendingRequests =
        new ConcurrentDictionary<Guid, PendingRequest>();
    private readonly TimeSpan _defaultResponseTimeout = TimeSpan.FromSeconds(2);
    #endregion

    #region 窗体初始化

    public SimpleMainForm()
    {
        InitializeComponent();
        InitializeServicesAsync();
    }

    private async void InitializeServicesAsync()
    {
        try
        {
            // 创建服务主机
            _host = Host.CreateDefaultBuilder()
                .ConfigureServices(
                    (context, services) =>
                    {
                        services.AddSingleton<ReactiveMessageBus>();
                        services.AddSingleton<CommunicationManager>();
                        services.AddLogging(builder =>
                        {
                            builder.AddConsole();
                            builder.SetMinimumLevel(LogLevel.Information);
                        });
                    }
                )
                .Build();

            // 启动服务
            _ = Task.Run(() => _host.RunAsync());

            // 获取服务实例
            _messageBus = _host.Services.GetRequiredService<ReactiveMessageBus>();
            _communicationManager = _host.Services.GetRequiredService<CommunicationManager>();

            var loggerFactory = _host.Services.GetRequiredService<ILoggerFactory>();
            _logger = loggerFactory.CreateLogger<SimpleMainForm>();

            // 初始化通讯管理器
            await _communicationManager.InitializeAsync();

            // 设置数据订阅 - 重要：延迟到所有控件初始化完成后
            this.Load += (s, e) =>
            {
                SetupDataSubscriptions();
                RefreshSerialPorts();
                InitializeTestCommands();

                // 为Designer创建的控件绑定事件
                BindControlEvents();
            };

            AppendLog("系统初始化完成", Color.Green);
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                $"系统初始化失败: {ex.Message}",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error
            );
        }
    }

    /// <summary>
    /// 绑定Designer创建的控件事件
    /// </summary>
    private void BindControlEvents()
    {
        // 串口相关事件
        if (serialConnectButton != null)
            serialConnectButton.Click += SerialConnect_Click;

        if (serialDisconnectButton != null)
            serialDisconnectButton.Click += SerialDisconnect_Click;

        if (serialSendButton != null)
            serialSendButton.Click += SerialSend_Click;

        if (serialSendTextBox != null)
            serialSendTextBox.KeyPress += SerialSendTextBox_KeyPress;

        // 测试相关事件
        if (startTestButton != null)
            startTestButton.Click += StartTest_Click;

        if (stopTestButton != null)
            stopTestButton.Click += StopTest_Click;

        if (addCommandButton != null)
            addCommandButton.Click += AddCommand_Click;

        if (removeCommandButton != null)
            removeCommandButton.Click += RemoveCommand_Click;

        // 添加导入Excel按钮事件
        var importExcelButton = FindControl<Button>(this, "importExcelButton");
        if (importExcelButton != null)
            importExcelButton.Click += ImportExcel_Click;
        // 绑定“查看波形”按钮事件
        var plotWaveformButton = FindControl<Button>(this, "plotWaveformButton");
        if (plotWaveformButton != null)
            plotWaveformButton.Click += PlotWaveform_Click;
        // 生成器相关事件
        if (generateCommandButton != null)
            generateCommandButton.Click += GenerateCommand_Click;

        if (addGeneratedCommandButton != null)
            addGeneratedCommandButton.Click += AddGeneratedCommand_Click;

        // 解析器相关事件
        if (parseButton != null)
            parseButton.Click += ParseCommand_Click;
    }

    #endregion

    #region 兼容性方法

    private void AppendLog(string message, Color color) => SafeAppendLog(message, color);

    private void AppendToTextBox(RichTextBox? textBox, string text, Color color) =>
        SafeAppendToTextBox(textBox, text, color);

    private void AppendTestLog(string message, Color color) => SafeAppendTestLog(message, color);

    #endregion

    #region 数据订阅和处理

    private void SetupDataSubscriptions()
    {
        if (_communicationManager == null)
        {
            SafeAppendLog("通讯管理器未初始化，无法设置数据订阅", Color.Red);
            return;
        }

        try
        {
            SafeAppendLog("正在设置数据订阅...", Color.Cyan);
            // 只在_dataSubject未初始化时才初始化
            if (_dataSubject == null)
            {
                _dataSubject = new Subject<ResponseDataMessage>();
            }

            // 串口数据接收订阅
            var serialDataSubscription = _communicationManager.SerialDataReceived.Subscribe(
                data =>
                {
                    try
                    {
                        if (IsDisposed || !IsHandleCreated)
                            return;

                        if (InvokeRequired)
                            BeginInvoke(new Action(() => SafeProcessSerialData(data)));
                        else
                            SafeProcessSerialData(data);
                    }
                    catch (ObjectDisposedException) { }
                    catch (InvalidOperationException) { }
                    catch (Exception ex)
                    {
                        SafeAppendLog($"处理串口数据时出错: {ex.Message}", Color.Red);
                    }
                },
                error => SafeAppendLog($"串口数据订阅错误: {error.Message}", Color.Red)
            );

            // 连接状态变化订阅
            var statusSubscription = _communicationManager.ConnectionStatusChanged.Subscribe(
                status =>
                {
                    try
                    {
                        if (IsDisposed || !IsHandleCreated)
                            return;

                        if (InvokeRequired)
                            BeginInvoke(new Action(() => SafeProcessStatusChange(status)));
                        else
                            SafeProcessStatusChange(status);
                    }
                    catch (ObjectDisposedException) { }
                    catch (InvalidOperationException) { }
                    catch (Exception ex)
                    {
                        SafeAppendLog($"处理状态变化时出错: {ex.Message}", Color.Red);
                    }
                },
                error => SafeAppendLog($"状态变化订阅错误: {error.Message}", Color.Red)
            );

            _subscriptions = new List<IDisposable> { serialDataSubscription, statusSubscription };
            SafeAppendLog("数据订阅设置完成", Color.Green);
        }
        catch (Exception ex)
        {
            SafeAppendLog($"设置数据订阅失败: {ex.Message}", Color.Red);
        }
    }

    private void SafeProcessSerialData(SerialDataMessage data)
    {
        if (_isDisposing || IsDisposed)
            return;

        try
        {
            var timestamp = data.Timestamp.ToString("HH:mm:ss.fff");

            if (data.Direction == SerialDataDirection.Received)
            {
                // 检查是否是测试响应
                if (_isTestRunning && !_pendingCommands.IsEmpty)
                    CheckTestResponse(data.Data, timestamp);

                // 只在非测试期间或允许日志时显示串口数据
                if (_enableSerialLogging || !_isTestRunning)
                {
                    var displayText = GetDisplayText(data.Data);
                    var message = $"[{timestamp}] {data.PortName} RX: {displayText}";
                    SafeAppendToTextBox(serialReceiveTextBox, message, Color.Lime);
                }

                // 始终进行Modbus解析，不受日志开关影响
                TryParseModbusMessage(data.Data, "RX", timestamp);

                if (!_isTestRunning)
                    SafeAppendLog($"接收到 {data.Data.Length} 字节数据", Color.Cyan);
            }
            else if (data.Direction == SerialDataDirection.Sent)
            {
                if (_enableSerialLogging || !_isTestRunning)
                {
                    var displayText = GetDisplayText(data.Data);
                    var message = $"[{timestamp}] {data.PortName} TX: {displayText}";
                    SafeAppendToTextBox(serialReceiveTextBox, message, Color.Yellow);
                }

                // 始终进行Modbus解析，不受日志开关影响
                TryParseModbusMessage(data.Data, "TX", timestamp);

                if (!_isTestRunning)
                    SafeAppendLog($"发送了 {data.Data.Length} 字节数据", Color.Orange);
            }
        }
        catch (Exception ex)
        {
            SafeAppendLog($"处理串口数据失败: {ex.Message}", Color.Red);
        }
    }

    #endregion

    #region 工具方法

    /// <summary>
    /// 根据解析结果创建ModbusParseResult对象
    /// </summary>
    /// <param name="parsedResult">解析结果字符串</param>
    /// <param name="functionCode">功能码</param>
    /// <param name="type">类型（请求/响应）</param>
    /// <returns>ModbusParseResult对象</returns>
    private ModbusParseResult CreateModbusParseResult(
        string parsedResult,
        string functionCode,
        string type,
        object OBJResult
    )
    {
        try
        {
            // 获取标准格式
            string standardFormat = GetStandardFormat(functionCode, type);

            // 创建ModbusParseResult对象
            return new ModbusParseResult(
                functionCode,
                type,
                standardFormat,
                parsedResult ?? "",
                "正确", // 默认状态为正确
                OBJResult
            );
        }
        catch (Exception ex)
        {
            // 如果创建过程中出错，返回一个默认的ModbusParseResult对象
            return new ModbusParseResult(
                functionCode,
                type,
                "未知",
                parsedResult ?? "",
                $"解析错误: {ex.Message}",
                OBJResult
            );
        }
    }

    /// <summary>
    /// 根据功能码和类型获取标准格式
    /// </summary>
    /// <param name="functionCode">功能码</param>
    /// <param name="type">类型（请求/响应）</param>
    /// <returns>标准格式字符串</returns>
    private string GetStandardFormat(string functionCode, string type)
    {
        // 根据功能码和类型返回对应的标准格式
        switch (functionCode)
        {
            case "03":
                return type == "请求"
                    ? "设备地址: 01, 功能码: 03, 寄存器地址: 0026, 寄存器数量: 0005, CRC: 6402"
                    : "设备地址: 01, 功能码: 03, 字节数: 10, 数据: 5 0 0 0 0, CRC: 1BE6";
            case "04":
                return type == "请求"
                    ? "设备地址: 01, 功能码: 04, 寄存器地址: 0026, 寄存器数量: 0005, CRC: D1C2"
                    : "设备地址: 01, 功能码: 04, 字节数: 10, 数据: 1 0 40 41 1, CRC: ACE3";
            case "06":
                return type == "请求"
                    ? "设备地址: 01, 功能码: 06, 寄存器地址: 0026, 写入值: 0005, CRC: A802"
                    : "设备地址: 01, 功能码: 06, 寄存器地址: 0026, 写入值: 0005, CRC: A802";
            case "10":
                return type == "请求"
                    ? "设备地址: 01,功能码: 10,寄存器地址: 0026,寄存器数量: 2,字节数: 4,数据: 00120034,CRC: D04F"
                    : "设备地址: 01, 功能码: 10, 寄存器地址: 0026, 寄存器数量: 2, CRC: A003";
            default:
                return "未知格式";
        }
    }

    private void RefreshSerialPorts()
    {
        if (serialPortComboBox == null)
            return;

        serialPortComboBox.Items.Clear();
        var ports = ReactiveSerialCommunication.GetAvailablePorts();
        if (ports.Length > 0)
        {
            serialPortComboBox.Items.AddRange(ports);
            serialPortComboBox.SelectedIndex = 0;
        }
    }

    /// <summary>
    /// 递归查找控件
    /// </summary>
    private T FindControl<T>(Control control, string controlName)
        where T : Control
    {
        foreach (Control c in control.Controls)
        {
            if (c.Name == controlName && c is T)
                return (T)c;

            if (c.HasChildren)
            {
                T foundControl = FindControl<T>(c, controlName);
                if (foundControl != null)
                    return foundControl;
            }
        }
        return null;
    }

    private void InitializeTestCommands()
    {
        // 初始化BindingList
        _commandItems = new BindingList<CommandItem>();
        if (commandsGrid != null)
        {
            // 清除现有列
            commandsGrid.Columns.Clear();

            // 设置DataSource
            commandsGrid.DataSource = _commandItems;

            // 添加列（如果需要）
            AddColumnsToDataGridView();

            // 设置DataGridView属性以支持自动调整列宽
            commandsGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
        }

        RefreshCommandsList();
    }

    private void AddColumnsToDataGridView()
    {
        if (commandsGrid.Columns.Count > 0)
            return; // 如果已有列，则不重新添加

        // 添加支持勾选的列
        var checkBoxColumn = new DataGridViewCheckBoxColumn
        {
            Name = "Selected",
            HeaderText = "选择",
            Width = 40,
            ReadOnly = false,
        };
        commandsGrid.Columns.Add(checkBoxColumn);

        commandsGrid.Columns.Add("Index", "序号");
        commandsGrid.Columns.Add("FunctionCode", "功能码");
        commandsGrid.Columns.Add("Device", "设备");
        commandsGrid.Columns.Add("Register", "寄存器");
        commandsGrid.Columns.Add("Value", "值");
        commandsGrid.Columns.Add("Command", "生成的报文");
        commandsGrid.Columns.Add("Description", "描述");
        commandsGrid.Columns.Add("Remark", "备注");

        // 设置列宽自适应内容
        commandsGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

        // 设置特定列的最小宽度
        commandsGrid.Columns["Index"].MinimumWidth = 40;
        commandsGrid.Columns["FunctionCode"].MinimumWidth = 60;
        commandsGrid.Columns["Device"].MinimumWidth = 60;
        commandsGrid.Columns["Register"].MinimumWidth = 80;
        commandsGrid.Columns["Value"].MinimumWidth = 80;
        commandsGrid.Columns["Command"].MinimumWidth = 150;
        commandsGrid.Columns["Description"].MinimumWidth = 100;
        commandsGrid.Columns["Remark"].MinimumWidth = 100;
    }

    private void RefreshCommandsList()
    {
        if (commandsGrid == null)
            return;

        // 清空现有项
        _commandItems.Clear();

        for (int i = 0; i < _testCommands.Count; i++)
        {
            var command = _testCommands[i];
            var description = GetCommandDescription(command);

            // 解析命令以获取详细信息
            var commandInfo = ParseCommandInfo(command);

            // 添加命令项到BindingList
            var commandItem = new CommandItem
            {
                IsSelected = true,
                Index = i + 1,
                FunctionCode = commandInfo.FunctionCode,
                Device = commandInfo.Device,
                Register = commandInfo.Register,
                Value = commandInfo.Value,
                Command = command,
                Description = description,
                Remark = "",
            };

            _commandItems.Add(commandItem);
        }

        // 设置DataGridView属性以支持自动调整列宽
        commandsGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    }

    /// <summary>
    /// 解析命令信息
    /// </summary>
    private CommandInfo ParseCommandInfo(string command)
    {
        try
        {
            var bytes = ParseHexString(command);
            if (bytes == null || bytes.Length < 8)
            {
                return new CommandInfo
                {
                    FunctionCode = "",
                    Device = "",
                    Register = "",
                    Value = "",
                };
            }

            return new CommandInfo
            {
                FunctionCode = bytes[1].ToString("X2"),
                Device = bytes[0].ToString("X2"),
                Register = $"{bytes[2]:X2}{bytes[3]:X2}",
                Value = $"{bytes[4]:X2}{bytes[5]:X2}",
            };
        }
        catch
        {
            return new CommandInfo
            {
                FunctionCode = "",
                Device = "",
                Register = "",
                Value = "",
            };
        }
    }

    /// <summary>
    /// 获取命令描述
    /// </summary>
    /// <param name="command">十六进制命令字符串
    /// <returns>命令描述字符串</returns>
    private string GetCommandDescription(string command)
    {
        try
        {
            var bytes = ParseHexString(command);
            if (bytes == null || bytes.Length < 3)
                return "未知命令";

            if (bytes[0] == 0x01)
            {
                return bytes[1] switch
                {
                    0x03 => "Modbus 读保持寄存器",
                    0x04 => "Modbus 读输入寄存器",
                    0x06 => "Modbus 写单个寄存器",
                    0x10 => "Modbus 写多个寄存器",
                    _ => $"Modbus 功能码 {bytes[1]:X2}",
                };
            }
            return "自定义命令";
        }
        catch
        {
            return "无效命令";
        }
    }

    /// <summary>
    /// 解析十六进制字符串为字节数组
    /// </summary>
    /// <param name="hexString">十六进制字符串
    /// <returns>字节数组</returns>
    private byte[]? ParseHexString(string hexString)
    {
        if (string.IsNullOrWhiteSpace(hexString))
            return null;

        hexString = hexString.Replace(" ", "").Replace("-", "").Replace(":", "").ToUpper();
        if (!System.Text.RegularExpressions.Regex.IsMatch(hexString, @"^[0-9A-F]*$"))
            return null;
        if (hexString.Length % 2 != 0)
            hexString = "0" + hexString;

        try
        {
            var bytes = new byte[hexString.Length / 2];
            for (int i = 0; i < bytes.Length; i++)
                bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
            return bytes;
        }
        catch
        {
            return null;
        }
    }

    /// <summary>
    /// 获取显示文本
    /// </summary>
    /// <param name="data">字节数组
    /// <returns>显示文本</returns>
    private string GetDisplayText(byte[] data)
    {
        try
        {
            bool hasUnprintableChars = data.Any(b => b < 32 && b != 9 && b != 10 && b != 13);
            if (hasUnprintableChars)
                return $"HEX: {Convert.ToHexString(data)}";
            else
            {
                var text = Encoding.UTF8.GetString(data);
                var hex = Convert.ToHexString(data);
                return $"{text} (HEX: {hex})";
            }
        }
        catch
        {
            return $"HEX: {Convert.ToHexString(data)}";
        }
    }

    /// <summary>
    /// 向指定的TextBox添加文本并设置颜色，确保线程安全
    /// </summary>
    /// <param name="textBox">目标TextBox控件
    /// <param name="text">要添加的文本
    /// <param name="color">文本颜色
    private void SafeAppendToTextBox(RichTextBox? textBox, string text, Color color)
    {
        if (textBox == null || textBox.IsDisposed || _isDisposing)
            return;

        // 检查窗体句柄是否已创建
        if (!textBox.IsHandleCreated)
            return;

        try
        {
            if (InvokeRequired)
            {
                // 使用BeginInvoke并添加异常处理
                BeginInvoke(
                    new Action(() =>
                    {
                        try
                        {
                            SafeAppendToTextBox(textBox, text, color);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"UI线程中添加文本失败: {ex.Message}");
                        }
                    })
                );
                return;
            }

            // 再次检查状态，因为在Invoke期间状态可能已改变
            if (textBox.IsDisposed || !textBox.IsHandleCreated || _isDisposing)
                return;

            textBox.SelectionStart = textBox.TextLength;
            textBox.SelectionLength = 0;
            textBox.SelectionColor = color;
            textBox.AppendText($"{text}\n");
            textBox.ScrollToCaret();

            // 防止文本框内容过多导致性能问题
            if (textBox.Lines.Length > 1000)
            {
                try
                {
                    var lines = textBox.Lines.Skip(200).ToArray();
                    textBox.Lines = lines;
                }
                catch
                {
                    // 如果清理失败，跳过，避免影响主要功能
                }
            }
        }
        catch (ObjectDisposedException)
        {
            // 控件已释放，这是正常情况，无需记录
        }
        catch (InvalidOperationException)
        {
            // 控件可能正在释放或跨线程访问，忽略
        }
        catch (ArgumentException)
        {
            // 可能是文本内容有问题，忽略
        }
        catch (Exception ex)
        {
            // 使用Console输出避免递归调用
            Console.WriteLine($"向文本框添加内容失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 安全添加日志
    /// </summary>
    /// <param name="message">日志消息
    /// <param name="color">日志颜色
    private void SafeAppendLog(string message, Color color)
    {
        if (_isDisposing || IsDisposed)
            return;

        try
        {
            var timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
            SafeAppendToTextBox(logTextBox, $"[{timestamp}] {message}", color);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"日志记录失败: {ex.Message}");
        }
    }

    /// <summary>
    /// 安全处理状态变化
    /// </summary>
    /// <param name="status">状态字符串
    private void SafeProcessStatusChange(string status)
    {
        if (_isDisposing || IsDisposed)
            return;

        try
        {
            SafeAppendLog(status, Color.Cyan);

            if (
                status.Contains("Serial")
                && serialStatusLabel != null
                && !serialStatusLabel.IsDisposed
            )
            {
                if (status.Contains("opened") || status.Contains("Connected"))
                {
                    serialStatusLabel.Text = "状态: 已连接";
                    serialStatusLabel.ForeColor = Color.Green;
                }
                else if (status.Contains("closed") || status.Contains("Error"))
                {
                    serialStatusLabel.Text = "状态: 未连接";
                    serialStatusLabel.ForeColor = Color.Red;
                }
            }
        }
        catch (Exception ex)
        {
            SafeAppendLog($"处理状态变化失败: {ex.Message}", Color.Red);
        }
    }

    #endregion

    /// <summary>
    /// 处理串口连接点击事件
    /// </summary>
    /// <param name="sender">事件源
    /// <param name="e">事件参数
    private async void SerialConnect_Click(object? sender, EventArgs e)
    {
        if (serialPortComboBox?.SelectedItem == null)
        {
            MessageBox.Show("请选择串口", "错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            AppendLog("未选择串口", Color.Red);
            return;
        }

        var portName = serialPortComboBox.SelectedItem.ToString()!;
        var baudRate = int.Parse(serialBaudComboBox?.SelectedItem?.ToString() ?? "9600");

        try
        {
            if (serialConnectButton != null)
                serialConnectButton.Enabled = false;
            AppendLog($"正在连接串口 {portName}，波特率: {baudRate}", Color.Cyan);

            if (_communicationManager != null)
            {
                var success = await _communicationManager.OpenSerialPortAsync(portName, baudRate);

                if (success)
                {
                    if (serialStatusLabel != null)
                    {
                        serialStatusLabel.Text = $"状态: 已连接 ({baudRate})";
                        serialStatusLabel.ForeColor = Color.Green;
                    }
                    if (serialConnectButton != null)
                        serialConnectButton.Enabled = false;
                    if (serialDisconnectButton != null)
                        serialDisconnectButton.Enabled = true;
                    if (serialPortComboBox != null)
                        serialPortComboBox.Enabled = false;
                    if (serialBaudComboBox != null)
                        serialBaudComboBox.Enabled = false;

                    AppendLog($"串口 {portName} 连接成功，波特率: {baudRate}", Color.Green);
                }
                else
                {
                    if (serialConnectButton != null)
                        serialConnectButton.Enabled = true;
                    AppendLog($"串口连接失败: {portName}", Color.Red);
                }
            }
        }
        catch (Exception ex)
        {
            if (serialConnectButton != null)
                serialConnectButton.Enabled = true;
            AppendLog($"连接串口时发生错误: {ex.Message}", Color.Red);
        }
    }

    /// <summary>
    /// 处理串口断开点击事件
    /// </summary>
    /// <param name="sender">事件源
    /// <param name="e">事件参数
    private async void SerialDisconnect_Click(object? sender, EventArgs e)
    {
        if (serialPortComboBox?.SelectedItem == null)
            return;

        var portName = serialPortComboBox.SelectedItem.ToString()!;

        try
        {
            // 如果测试正在运行，先停止测试
            if (_isTestRunning)
            {
                SafeAppendLog("检测到串口断开，自动停止测试", Color.Orange);
                StopTest();
            }

            if (_communicationManager != null)
            {
                await _communicationManager.CloseSerialPortAsync(portName);
            }

            if (serialStatusLabel != null)
            {
                serialStatusLabel.Text = "状态: 未连接";
                serialStatusLabel.ForeColor = Color.Red;
            }
            if (serialConnectButton != null)
                serialConnectButton.Enabled = true;
            if (serialDisconnectButton != null)
                serialDisconnectButton.Enabled = false;
            if (serialPortComboBox != null)
                serialPortComboBox.Enabled = true;
            if (serialBaudComboBox != null)
                serialBaudComboBox.Enabled = true;

            AppendLog($"串口 {portName} 已断开", Color.Orange);
        }
        catch (Exception ex)
        {
            AppendLog($"断开串口时发生错误: {ex.Message}", Color.Red);
        }
    }

    /// <summary>
    /// 处理串口发送点击事件
    /// </summary>
    /// <param name="sender">事件源
    /// <param name="e">事件参数
    private async void SerialSend_Click(object? sender, EventArgs e)
    {
        await SendSerialData();
    }

    /// <summary>
    /// 异步发送串口数据（字符串格式）并等待响应
    /// </summary>
    private async Task SendSerialData()
    {
        // 检查文本框是否为空或通讯管理器是否为null
        if (string.IsNullOrEmpty(serialSendTextBox?.Text) || _communicationManager == null)
            return;

        var portName = serialPortComboBox?.SelectedItem?.ToString(); // 获取选择的串口号
        if (string.IsNullOrEmpty(portName))
            return; // 如果串口号为空，返回

        try
        {
            var requestData = serialSendTextBox.Text;
            var requestBytes = Encoding.UTF8.GetBytes(requestData);

            // 发送请求并等待响应
            var response = await SendRequestAndWaitForResponse(
                portName,
                requestBytes,
                requestData,
                "字符串数据"
            );

            // 如果发送成功，清空文本框并记录日志
            if (response.Success)
            {
                // 确保在UI线程中更新UI控件
                if (serialSendTextBox != null)
                {
                    if (InvokeRequired)
                    {
                        Invoke(
                            new Action(() =>
                            {
                                if (!serialSendTextBox.IsDisposed)
                                    serialSendTextBox.Clear();
                            })
                        );
                    }
                    else
                    {
                        if (!serialSendTextBox.IsDisposed)
                            serialSendTextBox.Clear();
                    }
                }

                AppendLog($"数据发送成功", Color.Green);

                // 如果收到响应，显示响应信息
                if (response.ResponseData != null && response.ResponseData.Length > 0)
                {
                    var responseText = Encoding.UTF8.GetString(response.ResponseData);
                    AppendLog($"收到响应: {responseText}", Color.LightGreen);
                }
                else
                {
                    AppendLog($"未收到响应", Color.Orange);
                }
            }
            else
            {
                AppendLog($"数据发送失败", Color.Red);
            }
        }
        catch (Exception ex)
        {
            // 如果发送失败，记录错误日志
            AppendLog($"发送数据失败: {ex.Message}", Color.Red);
            // 可以考虑添加更详细的错误信息记录
            AppendLog($"发送数据失败详细信息: {ex}", Color.Red);
        }
    }

    /// <summary>
    /// 处理串口发送十六进制点击事件
    /// </summary>
    /// <param name="sender">事件源
    /// <param name="e">事件参数
    private void SerialSendHex_Click(object? sender, EventArgs e)
    {
        _ = Task.Run(async () => await SendSerialHexData());
    }

    /// <summary>
    /// 异步发送串口数据（十六进制格式）并等待响应
    /// </summary>
    private async Task SendSerialHexData()
    {
        // 检查文本框是否为空或通讯管理器是否为null
        if (string.IsNullOrEmpty(serialSendTextBox?.Text) || _communicationManager == null)
            return;

        var bytes = ParseHexString(serialSendTextBox.Text); // 解析十六进制字符串为字节数组
        if (bytes == null)
            return; // 如果解析失败，返回

        var portName = serialPortComboBox?.SelectedItem?.ToString(); // 获取选择的串口号
        if (string.IsNullOrEmpty(portName))
            return; // 如果串口号为空，返回

        try
        {
            // 发送请求并等待响应
            var response = await SendRequestAndWaitForResponse(
                portName,
                bytes,
                serialSendTextBox.Text,
                "十六进制数据"
            );

            // 如果发送成功，清空文本框并记录日志
            if (response.Success)
            {
                // 确保在UI线程中更新UI控件
                if (serialSendTextBox != null)
                {
                    if (InvokeRequired)
                    {
                        Invoke(
                            new Action(() =>
                            {
                                if (!serialSendTextBox.IsDisposed)
                                    serialSendTextBox.Clear();
                            })
                        );
                    }
                    else
                    {
                        if (!serialSendTextBox.IsDisposed)
                            serialSendTextBox.Clear();
                    }
                }

                AppendLog($"十六进制数据发送成功", Color.Green);

                // 如果收到响应，显示响应信息
                if (response.ResponseData != null)
                {
                    var responseHex = Convert.ToHexString(response.ResponseData);
                    AppendLog($"收到响应: {responseHex}", Color.LightGreen);
                }
                else
                {
                    AppendLog($"未收到响应", Color.Orange);
                }
            }
            else
            {
                AppendLog($"十六进制数据发送失败", Color.Red);
            }
        }
        catch (Exception ex)
        {
            // 如果发送失败，记录错误日志
            AppendLog($"发送十六进制数据失败: {ex.Message}", Color.Red);
            // 可以考虑添加更详细的错误信息记录
            AppendLog($"发送十六进制数据失败详细信息: {ex}", Color.Red);
        }
    }

    /// <summary>
    /// 处理串口发送文本框按键事件
    /// </summary>
    /// <param name="sender">事件源
    /// <param name="e">事件参数
    private void SerialSendTextBox_KeyPress(object? sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == (char)Keys.Enter)
        {
            e.Handled = true;
            _ = Task.Run(async () => await SendSerialData());
        }
    }

    /// <summary>
    /// 发送请求并等待响应
    /// </summary>
    private async Task<(bool Success, byte[] ResponseData)> SendRequestAndWaitForResponse(
        string portName,
        byte[] requestData,
        string requestDescription,
        string requestType
    )
    {
        try
        {
            // 确保_dataSubject已初始化
            if (_dataSubject == null)
            {
                _dataSubject = new Subject<ResponseDataMessage>();
            }

            AppendLog($"发送请求: {requestType}: {requestDescription}", Color.Cyan);
            var success = await _communicationManager!.SendSerialBytesAsync(portName, requestData);

            if (success)
            {
                try
                {
                    AppendLog(
                        $"请求发送成功，等待响应: {requestType}: {requestDescription}",
                        Color.Cyan
                    );
                    var requestFunctionCode = requestData[1];
                    int registerCount = 0;
                    var exLen = 0;

                    // 根据不同的功能码进行特定验证
                    switch (requestFunctionCode)
                    {
                        case 0x03:
                        case 0x04:
                            var c = new CommandInfo
                            {
                                FunctionCode = requestData[1].ToString("X2"),
                                Device = requestData[0].ToString("X2"),
                                Register = $"{requestData[2]:X2}{requestData[3]:X2}",
                                Value = $"{requestData[4]:X2}{requestData[5]:X2}",
                            };
                            exLen =
                                (
                                    int.Parse(c.Value, System.Globalization.NumberStyles.HexNumber)
                                    * 2
                                ) + 5;
                            registerCount = int.Parse(
                                c.Value,
                                System.Globalization.NumberStyles.HexNumber
                            );
                            break;
                        // 写单个寄存器功能码（06）
                        case 0x06:
                        case 0x10:
                            exLen = 8;
                            break;
                        default:
                            AppendLog(
                                $"不支持的功能码: {requestFunctionCode:X2}，请求类型: {requestType}: {requestDescription}",
                                Color.Red
                            );
                            return (false, Array.Empty<byte>()); // 返回失败状态
                    }

                    // 等待响应或超时
                    using var cts = new CancellationTokenSource(_defaultResponseTimeout);
                    var response = await WaitForResponseHelper.WaitForResponseAsync(
                        _communicationManager,
                        portName,
                        exLen, // 这里应该根据期望的响应长度进行设置
                        (int)_defaultResponseTimeout.TotalMilliseconds,
                        cts.Token
                    );

                    if (response.success)
                    {
                        var responseData = response.data;
                        AppendLog(
                            $"收到响应数据，长度: {responseData?.Length ?? 0} 字节",
                            Color.Cyan
                        );

                        // 验证响应是否正确
                        if (IsResponseValid(requestData, responseData))
                        {
                            AppendLog(
                                $"响应验证通过: {requestType}: {requestDescription}",
                                Color.Green
                            );

                            // 解析接收的报文
                            string parsedResponse = null;
                            ModbusParseResult parsedResponseObject = null;
                            try
                            {
                                var sendType = SendType.Response;
                                parsedResponse = ModbusAnalysisHelper.ProcessModbusMessage(
                                    responseData,
                                    sendType
                                );
                                var parsedResponseObj =
                                    ModbusAnalysisHelper.ProcessModbusMessageWithObj(
                                        responseData,
                                        sendType
                                    );

                                // 创建ModbusParseResult对象
                                if (!string.IsNullOrEmpty(parsedResponse))
                                {
                                    // 从请求数据中提取功能码
                                    string functionCode =
                                        requestData.Length > 1
                                            ? requestData[1].ToString("X2")
                                            : "未知";
                                    string type = "响应";
                                    parsedResponseObject = CreateModbusParseResult(
                                        parsedResponse,
                                        functionCode,
                                        type,
                                        parsedResponseObj
                                    );
                                }
                            }
                            catch (Exception ex)
                            {
                                AppendLog($"解析响应报文时出错: {ex.Message}", Color.Orange);
                            }

                            // 通知其他订阅者有新的响应数据，包括发送的报文、接收的报文以及时间信息
                            var responseMessage = new ResponseDataMessage(
                                requestData,
                                responseData,
                                DateTime.Now, // 发送时间
                                DateTime.Now, // 接收时间
                                $"{requestType}: {requestDescription}",
                                parsedResponseObject
                            );
                            _dataSubject.OnNext(responseMessage);
                            return (true, responseData);
                        }
                        else
                        {
                            AppendLog(
                                $"请求收到无效响应: {requestType}: {requestDescription}",
                                Color.Orange
                            );
                            return (true, Array.Empty<byte>()); // 发送成功但收到无效响应
                        }
                    }
                    else
                    {
                        // 超时，没有收到响应
                        AppendLog(
                            $"请求超时，未收到响应: {requestType}: {requestDescription}",
                            Color.Orange
                        );
                        return (true, Array.Empty<byte>()); // 发送成功但未收到响应
                    }
                }
                catch (OperationCanceledException)
                {
                    // 超时，没有收到响应
                    AppendLog(
                        $"请求超时，未收到响应: {requestType}: {requestDescription}",
                        Color.Orange
                    );
                    return (true, Array.Empty<byte>()); // 发送成功但未收到响应
                }
                catch (Exception ex)
                {
                    AppendLog($"等待响应时出错: {ex.Message}", Color.Red);
                    return (true, Array.Empty<byte>()); // 发送成功但处理响应时出错
                }
            }
            else
            {
                AppendLog($"请求发送失败: {requestType}: {requestDescription}", Color.Red);
                return (false, Array.Empty<byte>());
            }
        }
        catch (Exception ex)
        {
            AppendLog($"发送请求时出错: {ex.Message}", Color.Red);
            return (false, Array.Empty<byte>());
        }
    }

    /// <summary>
    /// 处理添加命令点击事件
    /// </summary>
    /// <param name="sender">事件源
    /// <param name="e">事件参数
    private void AddCommand_Click(object? sender, EventArgs e)
    {
        if (string.IsNullOrWhiteSpace(newCommandTextBox?.Text))
        {
            MessageBox.Show(
                "请输入命令内容",
                "提示",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information
            );
            return;
        }

        var command = newCommandTextBox.Text.Trim();
        var bytes = ParseHexString(command);
        if (bytes == null)
        {
            MessageBox.Show(
                "无效的十六进制格式，请使用格式: FF 00 AA BB",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error
            );
            return;
        }

        _testCommands.Add(command.ToUpper()); // 添加命令到测试命令列表

        // 添加到BindingList
        var commandInfo = ParseCommandInfo(command); // 解析命令信息
        var description = GetCommandDescription(command); // 获取命令描述
        var commandItem = new CommandItem
        {
            IsSelected = true,
            Index = _commandItems.Count + 1,
            FunctionCode = commandInfo.FunctionCode,
            Device = commandInfo.Device,
            Register = commandInfo.Register,
            Value = commandInfo.Value,
            Command = command.ToUpper(),
            Description = description,
            Remark = "",
        };

        _commandItems.Add(commandItem);

        newCommandTextBox.Clear();
        SafeAppendLog($"添加测试命令: {command}", Color.Green);
    }

    /// <summary>
    /// 处理删除命令点击事件
    /// </summary>
    /// <param name="sender">事件源
    /// <param name="e">事件参数
    private void RemoveCommand_Click(object? sender, EventArgs e)
    {
        if (commandsGrid?.SelectedRows.Count > 0)
        {
            var selectedIndex = commandsGrid.SelectedRows[0].Index;
            if (selectedIndex < _commandItems.Count)
            {
                var removedCommand = _commandItems[selectedIndex].Command;
                _commandItems.RemoveAt(selectedIndex);
                _testCommands.RemoveAt(selectedIndex);

                // 重新编号
                for (int i = 0; i < _commandItems.Count; i++)
                {
                    _commandItems[i].Index = i + 1;
                }

                SafeAppendLog($"删除测试命令: {removedCommand}", Color.Orange);
            }
        }
        else
        {
            MessageBox.Show(
                "请选择要删除的命令",
                "提示",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information
            );
        }
    }

    /// <summary>
    /// 导入Excel配置文件
    /// </summary>
    private void ImportExcel_Click(object? sender, EventArgs e)
    {
        try
        {
            using var openFileDialog = new OpenFileDialog
            {
                Filter = "Excel文件|*.xlsx|所有文件|*.*",
                Title = "选择测试命令配置文件",
            };

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                var importedCommands = ImportTestCommandsFromExcel(openFileDialog.FileName);
                if (importedCommands != null && importedCommands.Count > 0)
                {
                    // 清空现有命令
                    _testCommands.Clear();
                    _commandItems.Clear();

                    // 添加导入的命令
                    foreach (var command in importedCommands)
                    {
                        _testCommands.Add(command);
                    }

                    // 刷新显示
                    RefreshCommandsList();
                    SafeAppendLog($"成功导入 {importedCommands.Count} 条测试命令", Color.Green);
                }
            }
        }
        catch (Exception ex)
        {
            SafeAppendLog($"导入Excel文件失败: {ex.Message}", Color.Red);
            MessageBox.Show(
                $"导入失败: {ex.Message}",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error
            );
        }
    }

    /// <summary>
    /// 从Excel文件导入测试命令
    /// </summary>
    private List<string> ImportTestCommandsFromExcel(string filePath)
    {
        var commands = new List<string>();

        // 设置EPPlus许可证上下文
        ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;

        using var package = new ExcelPackage(new FileInfo(filePath));
        var worksheet = package.Workbook.Worksheets[0]; // 使用第一个工作表

        // 从第二行开始读取数据（第一行为标题行）
        for (int row = 2; row <= worksheet.Dimension.End.Row; row++)
        {
            try
            {
                // 检查是否勾选
                var isSelectedCell = worksheet.Cells[row, 1].Value;
                bool isSelected =
                    isSelectedCell?.ToString()?.ToLower() == "true"
                    || isSelectedCell?.ToString()?.ToLower() == "1"
                    || isSelectedCell?.ToString()?.ToLower() == "是"
                    || isSelectedCell?.ToString()?.ToLower() == "yes";

                // 如果未勾选，跳过该行
                if (!isSelected)
                    continue;

                // 读取各列数据
                var functionCode = worksheet.Cells[row, 2].Value?.ToString() ?? "";
                var device = worksheet.Cells[row, 3].Value?.ToString() ?? "";
                var register = worksheet.Cells[row, 4].Value?.ToString() ?? "";
                var value = worksheet.Cells[row, 5].Value?.ToString() ?? "";
                var remark = worksheet.Cells[row, 8].Value?.ToString() ?? "";

                // 生成命令
                var command = GenerateCommandFromExcelData(functionCode, device, register, value);
                if (!string.IsNullOrEmpty(command))
                {
                    commands.Add(command);
                }
            }
            catch (Exception ex)
            {
                SafeAppendLog($"处理Excel第{row}行时出错: {ex.Message}", Color.Orange);
            }
        }

        return commands;
    }

    /// <summary>
    /// 根据Excel数据生成命令
    /// </summary>
    private string GenerateCommandFromExcelData(
        string functionCode,
        string device,
        string register,
        string value
    )
    {
        try
        {
            // 确保输入数据格式正确
            device = device.PadLeft(2, '0').ToUpper();
            register = register.PadLeft(4, '0').ToUpper();
            value = value.PadLeft(4, '0').ToUpper();

            // 如果是功能码10，使用专门的生成方法
            if (functionCode == "10")
            {
                return GenerateFunction10CommandFromExcel(device, register, value);
            }

            // 构建命令字节数组（不含CRC）
            var commandBytes = new List<byte>();

            // 设备地址
            commandBytes.Add(Convert.ToByte(device, 16));

            // 功能码
            var funcCode = Convert.ToByte(functionCode, 16);
            commandBytes.Add(funcCode);

            // 寄存器地址（高字节在前）
            var regAddrValue = Convert.ToUInt16(register);
            commandBytes.Add((byte)(regAddrValue >> 8)); // 高字节
            commandBytes.Add((byte)(regAddrValue & 0xFF)); // 低字节

            // 值/数量（高字节在前）
            var valueRegCount = Convert.ToUInt16(value);
            commandBytes.Add((byte)(valueRegCount >> 8)); // 高字节
            commandBytes.Add((byte)(valueRegCount & 0xFF)); // 低字节

            // 计算CRC（使用现有方法）
            var crc = CalculateModbusCRC(commandBytes.ToArray());

            // 添加CRC（低字节在前）
            commandBytes.Add((byte)(crc & 0xFF)); // CRC低字节
            commandBytes.Add((byte)(crc >> 8)); // CRC高字节

            // 转换为十六进制字符串
            return string.Join(" ", commandBytes.Select(b => b.ToString("X2")));
        }
        catch (Exception ex)
        {
            SafeAppendLog(
                $"生成命令失败: 功能码={functionCode}, 设备={device}, 寄存器={register}, 值={value}, 错误={ex.Message}",
                Color.Red
            );
            return null;
        }
    }

    /// <summary>
    /// 根据Excel数据生成功能码10的命令（写多个寄存器）
    /// </summary>
    private string GenerateFunction10CommandFromExcel(
        string deviceAddr,
        string regAddr,
        string dataValues
    )
    {
        int countValues = 0;
        try
        {
            var values = dataValues.Split(
                   new char[] { ' ', ',', ';' },
                   StringSplitOptions.RemoveEmptyEntries
               );
            countValues = values.Length;
            // 解析数据值
            var dataList = new List<ushort>();
            
            // 如果没有提供数据值，使用寄存器数量作为默认值
            if (string.IsNullOrWhiteSpace(dataValues))
            {
                // 默认使用寄存器数量作为数据值
                var count = values.Length;
                for (int i = 0; i < count; i++)
                {
                    dataList.Add(0x0000); // 默认值为0
                }
            }
            else
            {
                foreach (var value in values)
                {
                    if (
                        ushort.TryParse(
                            value,
                            null,
                            out ushort parsedValue
                        )
                    )
                    {
                        dataList.Add(parsedValue);
                    }
                    else
                    {
                        throw new ArgumentException($"无效的数据值: {value}");
                    }
                }
            }

            // 计算字节数（每个寄存器值2个字节）
            var actualRegCount = (ushort)dataList.Count;
            var byteCount = (byte)(actualRegCount * 2);

            // 构建命令字节数组（不含CRC）
            var commandBytes = new List<byte>();
            commandBytes.Add(Convert.ToByte(deviceAddr, 16)); // 设备地址
            commandBytes.Add(0x10); // 功能码 10

            // 寄存器地址（高字节在前）
            var regAddrValue = Convert.ToUInt16(regAddr);
            commandBytes.Add((byte)(regAddrValue >> 8)); // 高字节
            commandBytes.Add((byte)(regAddrValue & 0xFF)); // 低字节

            // 寄存器数量（高字节在前）
            commandBytes.Add((byte)(actualRegCount >> 8)); // 高字节
            commandBytes.Add((byte)(actualRegCount & 0xFF)); // 低字节

            // 字节数
            commandBytes.Add(byteCount);

            // 数据字节（每个寄存器值高字节在前）
            foreach (var dataValue in dataList)
            {
                commandBytes.Add((byte)(dataValue >> 8)); // 高字节
                commandBytes.Add((byte)(dataValue & 0xFF)); // 低字节
            }

            // 计算CRC
            var crc = CalculateModbusCRC(commandBytes.ToArray());

            // 添加CRC（低字节在前）
            commandBytes.Add((byte)(crc & 0xFF)); // CRC低字节
            commandBytes.Add((byte)(crc >> 8)); // CRC高字节

            // 转换为十六进制字符串
            return string.Join(" ", commandBytes.Select(b => b.ToString("X2")));
        }
        catch (Exception ex)
        {
            SafeAppendLog(
                $"生成功能码10命令失败: 设备={deviceAddr}, 寄存器={regAddr}, 数量={countValues}, 数据={dataValues}, 错误={ex.Message}",
                Color.Red
            );
            return null;
        }
    }

    /// <summary>
    /// 功能码选择变化事件处理
    /// </summary>
    private void FunctionCodeCombo_SelectedIndexChanged(object? sender, EventArgs e)
    {
        if (functionCodeCombo?.SelectedItem == null)
            return;

        var selectedFuncCode = functionCodeCombo.SelectedItem.ToString();
        bool isFunction10 = selectedFuncCode == "10";

        // 控制功能码10专用控件的显示/隐藏
        if (dataLabel != null)
            dataLabel.Visible = isFunction10;
        if (dataValueBox != null)
            dataValueBox.Visible = isFunction10;
        if (dataHintLabel != null)
            dataHintLabel.Visible = isFunction10;

        // 调整数量标签的文本
        if (registerCountBox != null)
        {
            var countLabel = commandGeneratorGroup
                ?.Controls.OfType<Label>()
                .FirstOrDefault(l => l.Text == "数量:" || l.Text == "值:");
            if (countLabel != null)
            {
                countLabel.Text = isFunction10 ? "数量:" : "值:";
            }
        }

        SafeAppendLog($"切换到功能码 {selectedFuncCode}", Color.Cyan);
    }

    private byte[] GetResponseData(string command)
    {
        try
        {
            // 解析命令为字节数组
            var commandBytes = ParseHexString(command);
            if (commandBytes == null)
            {
                SafeAppendLog($"解析命令失败: {command}", Color.Red);
                return null;
            }

            // 获取当前选择的串口号
            string? portName = serialPortComboBox?.SelectedItem?.ToString();
            if (string.IsNullOrEmpty(portName))
            {
                SafeAppendLog("未选择串口", Color.Red);
                return null;
            }

            return null;
        }
        catch (Exception ex)
        {
            SafeAppendLog($"获取回复数据时出错: {ex.Message}", Color.Red);
            return null;
        }
    }

    private readonly Subject<DataMessage> dataSubject = new Subject<DataMessage>();

    private void PlotWaveform_Click(object? sender, EventArgs e)
    {
        if (commandsGrid?.SelectedRows.Count <= 0)
        {
            MessageBox.Show(
                "请选择要查看波形的命令",
                "提示",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information
            );
            return;
        }

        var selectedRow = commandsGrid.SelectedRows[0];
        int selectedIndex = selectedRow.Index;

        // 获取选中的命令项
        var selectedItem = _commandItems[selectedIndex];

        // 检查功能码是否为 03 或 04
        if (selectedItem.FunctionCode != "03" && selectedItem.FunctionCode != "04")
        {
            MessageBox.Show(
                "当前选择的命令功能码不是 03 或 04",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error
            );
            return;
        }

        // 根据 Value 字段判断寄存器数量
        int registerCount;
        if (!int.TryParse(selectedItem.Value, out registerCount))
        {
            MessageBox.Show(
                "Value 字段格式不正确",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error
            );
            return;
        }

        // 如果寄存器数量为 2，则需要获取回复数据并生成波形
        if (registerCount > 1)
        {
            Form1 form1 = new Form1(dataSubject);
            form1.Show();
            return;
        }
        else
        {
            MessageBox.Show(
                "当前选择的命令值不是 2",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error
            );
        }
    }

    private void PlotWaveform(int value1, int value2)
    {
        // 创建 ScottPlot 窗口
        var plt = new ScottPlot.Plot();

        // 添加数据点
        plt.AddScatter(new double[] { 0, 1 }, new double[] { value1, value2 });

        // 显示图表
        plt.SaveFig("waveform.png");
        System.Diagnostics.Process.Start("waveform.png");
    }

    private void GenerateCommand_Click(object? sender, EventArgs e)
    {
        try
        {
            if (functionCodeCombo?.SelectedItem == null)
            {
                MessageBox.Show(
                    "请选择功能码",
                    "提示",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information
                );
                return;
            }

            var funcCode = functionCodeCombo.SelectedItem.ToString()!;
            var deviceAddr = deviceAddressBox?.Text?.Trim() ?? "01";
            var regAddr = registerAddressBox?.Text?.Trim() ?? "0";
            var regCount = registerCountBox?.Text?.Trim() ?? "1";

            // 验证输入格式
            if (!IsValidHex(deviceAddr) || !IsValidHex(regAddr) || !IsValidHex(regCount))
            {
                MessageBox.Show(
                    "请输入有效的十六进制值",
                    "格式错误",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Warning
                );
                return;
            }

            // 确保格式正确
            deviceAddr = deviceAddr.PadLeft(2, '0').ToUpper();
            //regAddr = regAddr.PadLeft(4, '0').ToUpper();
            //regCount = regCount.PadLeft(4, '0').ToUpper();

            string fullCommand;

            if (funcCode == "10") // 功能码10：写多个寄存器
            {
                fullCommand = GenerateFunction10Command(deviceAddr, regAddr, regCount);
            }
            else // 其他功能码
            {
                fullCommand = GenerateStandardCommand(funcCode, deviceAddr, regAddr, regCount);
            }

            if (generatedCommandTextBox != null)
            {
                generatedCommandTextBox.Text = fullCommand;
            }

            SafeAppendLog($"生成Modbus命令: {fullCommand}", Color.Green);
        }
        catch (Exception ex)
        {
            SafeAppendLog($"生成命令失败: {ex.Message}", Color.Red);
            MessageBox.Show(
                $"生成命令失败: {ex.Message}",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error
            );
        }
    }

    /// <summary>
    /// 生成功能码10的命令（写多个寄存器）
    /// </summary>
    private string GenerateFunction10Command(string deviceAddr, string regAddr, string regCount)
    {
        var dataValues = dataValueBox?.Text?.Trim() ?? "1234";

        // 解析数据值
        var dataList = new List<ushort>();
        var values = dataValues.Split(
            new char[] { ' ', ',', ';' },
            StringSplitOptions.RemoveEmptyEntries
        );

        foreach (var value in values)
        {
            if (
                ushort.TryParse(
                    value,
                    null,
                    out ushort parsedValue
                )
            )
            {
                dataList.Add(parsedValue);
            }
            else
            {
                throw new ArgumentException($"无效的数据值: {value}");
            }
        }

        // 计算字节数（每个寄存器值2个字节）
        var actualRegCount = (ushort)dataList.Count;
        var byteCount = (byte)(actualRegCount * 2);

        // 构建命令字节数组（不含CRC）
        var commandBytes = new List<byte>();
        commandBytes.Add(Convert.ToByte(deviceAddr, 16)); // 设备地址
        commandBytes.Add(0x10); // 功能码 10

        // 寄存器地址（高字节在前）
        var regAddrValue = Convert.ToUInt16(regAddr);
        commandBytes.Add((byte)(regAddrValue >> 8)); // 高字节
        commandBytes.Add((byte)(regAddrValue & 0xFF)); // 低字节

        // 寄存器数量（高字节在前）
        commandBytes.Add((byte)(actualRegCount >> 8)); // 高字节
        commandBytes.Add((byte)(actualRegCount & 0xFF)); // 低字节

        // 字节数
        commandBytes.Add(byteCount);

        // 数据字节（每个寄存器值高字节在前）
        foreach (var dataValue in dataList)
        {
            commandBytes.Add((byte)(dataValue >> 8)); // 高字节
            commandBytes.Add((byte)(dataValue & 0xFF)); // 低字节
        }

        // 计算CRC
        var crc = CalculateModbusCRC(commandBytes.ToArray());

        // 添加CRC（低字节在前）
        commandBytes.Add((byte)(crc & 0xFF)); // CRC低字节
        commandBytes.Add((byte)(crc >> 8)); // CRC高字节

        // 转换为十六进制字符串
        return string.Join(" ", commandBytes.Select(b => b.ToString("X2")));
    }

    /// <summary>
    /// 生成标准功能码的命令（03、04、06）
    /// </summary>
    private string GenerateStandardCommand(
        string funcCode,
        string deviceAddr,
        string regAddr,
        string regCount
    )
    {
        // 构建命令字节数组（不含CRC）
        var commandBytes = new List<byte>();
        commandBytes.Add(Convert.ToByte(deviceAddr, 16)); // 设备地址
        commandBytes.Add(Convert.ToByte(funcCode, 16)); // 功能码

        // 寄存器地址（高字节在前）
        var regAddrValue = Convert.ToUInt16(regAddr);
        commandBytes.Add((byte)(regAddrValue >> 8)); // 高字节
        commandBytes.Add((byte)(regAddrValue & 0xFF)); // 低字节

        // 寄存器数量/值（高字节在前）
        var regCountValue = Convert.ToUInt16(regCount);
        commandBytes.Add((byte)(regCountValue >> 8)); // 高字节
        commandBytes.Add((byte)(regCountValue & 0xFF)); // 低字节

        // 计算CRC
        var crc = CalculateModbusCRC(commandBytes.ToArray());

        // 添加CRC（低字节在前）
        commandBytes.Add((byte)(crc & 0xFF)); // CRC低字节
        commandBytes.Add((byte)(crc >> 8)); // CRC高字节

        // 转换为十六进制字符串
        return string.Join(" ", commandBytes.Select(b => b.ToString("X2")));
    }

    private void AddGeneratedCommand_Click(object? sender, EventArgs e)
    {
        if (string.IsNullOrWhiteSpace(generatedCommandTextBox?.Text))
        {
            MessageBox.Show(
                "请先生成命令",
                "提示",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information
            );
            return;
        }

        var command = generatedCommandTextBox.Text.Trim();
        _testCommands.Add(command);
        RefreshCommandsList();
        SafeAppendLog($"添加生成的测试命令: {command}", Color.Green);

        // 清空生成结果
        if (generatedCommandTextBox != null)
            generatedCommandTextBox.Clear();
    }

    private void PresetCommand_Click(object? sender, EventArgs e)
    {
        // 实现预设命令选择
        SafeAppendLog("选择预设命令", Color.Blue);
    }

    private SendType DetectMessageType(byte[] bytes)
    {
        if (bytes.Length < 3)
            return SendType.Request;

        var functionCode = bytes[1];

        // 如果功能码最高位为1，通常是错误响应
        if ((functionCode & 0x80) != 0)
        {
            return SendType.Response;
        }

        // 根据常见长度模式判断
        switch (functionCode)
        {
            case 0x03:
            case 0x04:
                // 读取功能：如果长度为8，通常是请求；如果长度更长且第3字节是数据长度，通常是响应
                if (bytes.Length == 8)
                {
                    return SendType.Request;
                }
                else if (bytes.Length > 5 && bytes[2] == bytes.Length - 5)
                {
                    return SendType.Response;
                }
                break;

            case 0x06:
                // 写单个寄存器：请求和响应长度都是8字节，难以区分，默认请求
                return SendType.Request;

            case 0x10:
                // 写多个寄存器：请求包含数据，响应只有地址和数量
                if (bytes.Length == 8)
                {
                    return SendType.Response;
                }
                else if (bytes.Length > 9)
                {
                    return SendType.Request;
                }
                break;
        }

        // 默认返回请求类型
        return SendType.Request;
    }

    private void ParseCommand_Click(object? sender, EventArgs e)
    {
        if (string.IsNullOrWhiteSpace(parseInputBox?.Text))
        {
            MessageBox.Show(
                "请输入要解析的报文",
                "提示",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information
            );
            return;
        }

        try
        {
            var hexString = parseInputBox.Text.Trim();
            var bytes = ParseHexString(hexString);

            if (bytes == null || bytes.Length < 3)
            {
                if (parseResultBox != null)
                {
                    parseResultBox.Clear();
                    parseResultBox.SelectionColor = Color.Red;
                    parseResultBox.AppendText("错误: 无效的报文格式或长度不足\n");
                    parseResultBox.AppendText($"输入: {hexString}\n");
                    parseResultBox.AppendText("要求: 至少3个字节的有效十六进制数据");
                }
                return;
            }

            SafeAppendLog($"开始解析报文: {Convert.ToHexString(bytes)}", Color.Cyan);

            // 确定报文类型
            var parseType = parseTypeCombo?.SelectedIndex ?? 2;
            SendType sendType;

            if (parseType == 0) // 请求报文
            {
                sendType = SendType.Request;
            }
            else if (parseType == 1) // 响应报文
            {
                sendType = SendType.Response;
            }
            else // 自动识别
            {
                sendType = DetectMessageType(bytes);
            }

            // 使用ModbusAnalysisHelper解析
            var result = ModbusAnalysisHelper.ProcessModbusMessage(bytes, sendType);

            // 显示解析结果
            DisplayParseResult(hexString, bytes, sendType, result);

            SafeAppendLog($"报文解析完成: {sendType}", Color.Green);
        }
        catch (Exception ex)
        {
            var errorMsg = $"解析报文失败: {ex.Message}";
            AppendLog(errorMsg, Color.Red);

            if (parseResultBox != null)
            {
                parseResultBox.Clear();
                parseResultBox.SelectionColor = Color.Red;
                parseResultBox.AppendText($"解析异常: {ex.Message}\n");
                parseResultBox.AppendText($"异常类型: {ex.GetType().Name}\n");
                if (ex.InnerException != null)
                {
                    parseResultBox.AppendText($"内部异常: {ex.InnerException.Message}\n");
                }
            }
        }
    }

    private string GetFunctionCodeName(byte functionCode)
    {
        return functionCode switch
        {
            0x01 => "读线圈",
            0x02 => "读离散输入",
            0x03 => "读保持寄存器",
            0x04 => "读输入寄存器",
            0x05 => "写单个线圈",
            0x06 => "写单个寄存器",
            0x0F => "写多个线圈",
            0x10 => "写多个寄存器",
            0x20 => "自定义读取",
            0x1E => "自定义功能",
            0x39 => "自定义功能",
            _ => $"未知功能码 (0x{functionCode:X2})",
        };
    }

    private void DisplayParseResult(
        string originalHex,
        byte[] bytes,
        SendType sendType,
        string parseResult
    )
    {
        if (parseResultBox == null)
            return;

        parseResultBox.Clear();

        // 显示基本信息
        parseResultBox.SelectionColor = Color.Yellow;
        parseResultBox.AppendText($"=== Modbus报文解析结果 ===\n");

        parseResultBox.SelectionColor = Color.Cyan;
        parseResultBox.AppendText($"原始报文: {originalHex}\n");
        parseResultBox.AppendText($"字节长度: {bytes.Length}\n");
        parseResultBox.AppendText(
            $"报文类型: {(sendType == SendType.Request ? "请求" : "响应")}\n\n"
        );

        // 显示字节分析
        parseResultBox.SelectionColor = Color.LightGreen;
        parseResultBox.AppendText("字节分析:\n");
        parseResultBox.SelectionColor = Color.White;

        if (bytes.Length >= 1)
            parseResultBox.AppendText($"  设备地址: 0x{bytes[0]:X2} ({bytes[0]})\n");
        if (bytes.Length >= 2)
        {
            var funcCode = bytes[1];
            var isError = (funcCode & 0x80) != 0;
            if (isError)
            {
                parseResultBox.SelectionColor = Color.Red;
                parseResultBox.AppendText(
                    $"  功能码: 0x{funcCode:X2} (错误响应, 原功能码: 0x{(funcCode & 0x7F):X2})\n"
                );
                parseResultBox.SelectionColor = Color.White;
            }
            else
            {
                parseResultBox.AppendText(
                    $"  功能码: 0x{funcCode:X2} ({GetFunctionCodeName(funcCode)})\n"
                );
            }
        }

        // 显示详细解析结果
        parseResultBox.SelectionColor = Color.LightBlue;
        parseResultBox.AppendText("\n详细解析:\n");
        parseResultBox.SelectionColor = Color.White;
        parseResultBox.AppendText($"{parseResult}\n");

        // CRC验证
        if (bytes.Length >= 3)
        {
            var dataBytes = new byte[bytes.Length - 2];
            Array.Copy(bytes, 0, dataBytes, 0, dataBytes.Length);
            var calculatedCrc = CalculateModbusCRC(dataBytes);
            var receivedCrc = (ushort)(bytes[bytes.Length - 2] | (bytes[bytes.Length - 1] << 8));

            parseResultBox.SelectionColor = Color.LightGray;
            parseResultBox.AppendText("\nCRC验证:\n");
            parseResultBox.SelectionColor = receivedCrc == calculatedCrc ? Color.Green : Color.Red;
            parseResultBox.AppendText($"  接收CRC: 0x{receivedCrc:X4}\n");
            parseResultBox.AppendText($"  计算CRC: 0x{calculatedCrc:X4}\n");
            parseResultBox.AppendText(
                $"  验证结果: {(receivedCrc == calculatedCrc ? "✓ 正确" : "✗ 错误")}\n"
            );
        }
    }

    private void QuickParse_Click(object? sender, EventArgs e)
    {
        if (sender is Button btn && btn.Tag is string sample)
        {
            if (parseInputBox != null)
            {
                parseInputBox.Text = sample;
            }

            // 自动解析
            ParseCommand_Click(null, EventArgs.Empty);
        }
    }

    private void StartTest_Click(object? sender, EventArgs e)
    {
        if (
            serialPortComboBox?.SelectedItem == null
            || serialStatusLabel?.Text?.Contains("已连接") != true
        )
        {
            MessageBox.Show(
                "请先连接串口再开始测试",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Warning
            );
            return;
        }

        // 检查是否有被勾选的命令
        var selectedCommands = _commandItems.Where(c => c.IsSelected).ToList();
        if (selectedCommands.Count == 0)
        {
            MessageBox.Show(
                "请先勾选至少一个测试命令",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Warning
            );
            return;
        }

        // 检查是否已在测试中
        if (_isTestRunning)
        {
            MessageBox.Show(
                "测试已在运行中",
                "提示",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information
            );
            return;
        }

        try
        {
            // 初始化测试状态
            _isTestRunning = true;
            _testStartTime = DateTime.Now;
            _testCount = 0;
            _testSuccessCount = 0;
            _testFailureCount = 0;
            _commandIndex = 0;
            _pendingCommands.Clear();
            _enableSerialLogging = false;

            // 释放之前的取消令牌
            try
            {
                _testCancellationToken?.Dispose();
            }
            catch (Exception ex)
            {
                SafeAppendLog($"释放旧取消令牌异常: {ex.Message}", Color.Gray);
            }

            // 创建新的取消令牌
            _testCancellationToken = new CancellationTokenSource();

            // 更新UI
            SafeUpdateTestUI(true);
            UpdateTestStats();

            AppendTestLog(
                $"测试开始 - 持续时间: {testDuration?.Value}分钟, 间隔: {testIntervalMin?.Value}~{testIntervalMax?.Value}ms",
                Color.Green
            );
            AppendTestLog($"测试命令数量: {selectedCommands.Count}", Color.Cyan);
            SafeAppendLog($"极限测试开始 - 命令数: {selectedCommands.Count}", Color.Green);

            // 启动异步测试任务
            _testTask = Task.Run(
                async () =>
                {
                    try
                    {
                        await RunTestAsync(_testCancellationToken.Token);
                    }
                    catch (Exception ex)
                    {
                        SafeAppendLog($"测试任务异常: {ex.Message}", Color.Red);
                    }
                },
                _testCancellationToken.Token
            );

            SafeAppendLog("测试任务已启动", Color.Green);
        }
        catch (Exception ex)
        {
            _isTestRunning = false;
            SafeUpdateTestUI(false);
            SafeAppendLog($"启动测试失败: {ex.Message}", Color.Red);
            MessageBox.Show(
                $"启动测试失败: {ex.Message}",
                "错误",
                MessageBoxButtons.OK,
                MessageBoxIcon.Error
            );
        }
    }

    private void StopTest_Click(object? sender, EventArgs e)
    {
        StopTest();
    }

    private void StopTest()
    {
        if (_isDisposing)
            return; // 防止在窗体释放过程中执行

        try
        {
            // 设置停止标志
            _isTestRunning = false;

            // 恢复串口日志
            _enableSerialLogging = true;

            // 取消任务 - 使用CancellationTokenSource控制任务生命周期
            try
            {
                _testCancellationToken?.Cancel();
                SafeAppendLog("已发送取消信号给测试任务", Color.Cyan);
            }
            catch (ObjectDisposedException)
            {
                // CancellationTokenSource已被释放，忽略
                SafeAppendLog("CancellationTokenSource已释放", Color.Gray);
            }
            catch (Exception ex)
            {
                SafeAppendLog($"取消测试任务异常: {ex.Message}", Color.Orange);
            }

            // 更新UI - 使用安全的方式
            SafeUpdateTestUI(false);

            var duration = DateTime.Now - _testStartTime;
            var successRate = _testCount > 0 ? (_testSuccessCount * 100.0 / _testCount) : 0;

            AppendTestLog(
                $"测试结束 - 耗时: {duration:hh\\:mm\\:ss}, 成功率: {successRate:F1}%",
                Color.Red
            );
            SafeAppendLog(
                $"极限测试结束 - 总次数: {_testCount}, 成功: {_testSuccessCount}, 失败: {_testFailureCount}",
                Color.Orange
            );
        }
        catch (Exception ex)
        {
            // 捕获所有异常，防止程序崩溃
            SafeAppendLog($"停止测试时发生异常: {ex.Message}", Color.Red);
        }
    }

    private void SafeAppendTestLog(string message, Color color)
    {
        SafeAppendToTextBox(testLogTextBox, message, color);
    }

    /// <summary>
    /// 尝试解析Modbus消息
    /// </summary>
    /// <param name="data">字节数组数据</param>
    /// <param name="direction">数据方向（RX或TX）</param>
    /// <param name="timestamp">时间戳</param>
    private void TryParseModbusMessage(byte[] data, string direction, string timestamp)
    {
        try
        {
            // 检查数据长度，确保至少有设备地址、功能码和CRC（3+2=5字节）
            if (data.Length < 5)
            {
                SafeAppendToTextBox(
                    serialReceiveTextBox,
                    $"    → [{timestamp}] {direction} 报文太短，无法解析 (HEX: {Convert.ToHexString(data)})",
                    Color.Orange
                );
                return;
            }

            // 检查是否是Modbus协议（设备地址在合理范围内）
            if (data[0] == 0x00 || data[0] > 0xF7)
            {
                SafeAppendToTextBox(
                    serialReceiveTextBox,
                    $"    → [{timestamp}] {direction} 非Modbus数据 (HEX: {Convert.ToHexString(data)})",
                    Color.Gray
                );
                return;
            }

            // 检验CRC校验码
            if (!VerifyModbusCRC(data))
            {
                SafeAppendToTextBox(
                    serialReceiveTextBox,
                    $"    → [{timestamp}] {direction} CRC校验失败 (HEX: {Convert.ToHexString(data)})",
                    Color.Red
                );
                return;
            }

            // 判断是请求还是响应
            SendType sendType = DetermineMessageType(data, direction);

            // 验证报文长度是否符合协议规范
            var lengthValidationResult = ValidateModbusMessageLength(data, sendType);
            if (!lengthValidationResult)
            {
                // 添加详细的调试信息，但不阻止解析（作为警告）
                var functionCode = data[1];
                var expectedLength = GetExpectedModbusLength(data, sendType);
                var debugInfo =
                    $"功能码:{functionCode:X2}, 类型:{sendType}, 实际长度:{data.Length}, 期望长度:{expectedLength}";
                SafeAppendToTextBox(
                    serialReceiveTextBox,
                    $"    ⚠️ [{timestamp}] {direction} 警告: 报文长度可能不符合规范 ({debugInfo}) (HEX: {Convert.ToHexString(data)})",
                    Color.Orange
                );
                // 继续解析，不返回
            }

            // 使用ModbusAnalysisHelper进行完整解析
            string analysisResult = ModbusAnalysisHelper.ProcessModbusMessage(data, sendType);

            // 显示解析结果
            var messageType = sendType == SendType.Request ? "请求" : "响应"; // 根据类型设置消息类型
            var color = direction == "TX" ? Color.Yellow : Color.LightGreen; // 根据方向设置颜色

            SafeAppendToTextBox(
                serialReceiveTextBox,
                $"    → [{timestamp}] {direction} Modbus{messageType}解析: {analysisResult}", // 格式化解析结果
                color
            );
        }
        catch (Exception ex)
        {
            // 出现解析错误时，显示原始数据
            SafeAppendToTextBox(
                serialReceiveTextBox,
                $"    → [{timestamp}] {direction} 解析失败: {ex.Message} (HEX: {Convert.ToHexString(data)})", // 格式化错误信息
                Color.Red
            );
        }
    }

    /// <summary>
    /// 检查测试响应
    /// </summary>
    /// <param name="responseData">响应数据</param>
    /// <param name="timestamp">时间戳</param>
    private void CheckTestResponse(byte[] responseData, string timestamp)
    {
        // 如果测试未运行或待响应命令为空，返回
        if (!_isTestRunning || _pendingCommands.IsEmpty)
            return;

        // 简单的响应验证：检查是否是有效的Modbus响应
        if (responseData.Length < 3)
            return;

        // 检查设备地址是否匹配（假设我们的测试命令都是发给设备01）
        if (responseData[0] != 0x01)
            return;

        // 验证功能码（响应的功能码应该与请求相同，或者是错误响应）
        var functionCode = responseData[1];
        bool isValidResponse =
            functionCode == 0x03
            || functionCode == 0x04
            || functionCode == 0x06
            || functionCode == 0x10
            || (functionCode & 0x80) != 0; // 支持所有常用功能码和错误响应

        if (!isValidResponse)
            return;

        // 找到最老的待响应命令（FIFO原则）
        var oldestCommand = _pendingCommands.OrderBy(kvp => kvp.Value).FirstOrDefault();
        if (oldestCommand.Key == 0)
            return; // 没有待响应命令

        // 移除已响应的命令
        if (_pendingCommands.TryRemove(oldestCommand.Key, out var sendTime))
        {
            lock (_testLock)
            {
                _testSuccessCount++; // 增加成功次数
            }

            var responseTime = DateTime.Now - sendTime; // 计算响应时间
            var responseHex = Convert.ToHexString(responseData); // 获取响应数据的十六进制表示

            AppendTestLog(
                $"[{timestamp}] 第{oldestCommand.Key}次响应: {responseHex} (响应时间: {responseTime.TotalMilliseconds:F0}ms)", // 格式化响应日志
                Color.LightGreen
            );

            // 更新统计
            UpdateTestStats();
            SafeAppendLog(
                $"命令{oldestCommand.Key}收到响应，耗时{responseTime.TotalMilliseconds:F0}ms", // 格式化成功日志
                Color.Green
            );
        }
    }

    /// <summary>
    /// 更新测试统计信息
    /// </summary>
    private void UpdateTestStats()
    {
        // 如果需要在UI线程中调用，递归调用自身
        if (InvokeRequired)
        {
            Invoke(UpdateTestStats);
            return;
        }

        if (testCountLabel != null)
            testCountLabel.Text = $"总次数: {_testCount}"; // 更新总次数标签
        if (testSuccessLabel != null)
            testSuccessLabel.Text = $"成功: {_testSuccessCount}"; // 更新成功次数标签
        if (testFailureLabel != null)
            testFailureLabel.Text = $"失败: {_testFailureCount}"; // 更新失败次数标签

        var successRate = _testCount > 0 ? (_testSuccessCount * 100.0 / _testCount) : 0; // 计算成功率
        if (testStatusLabel != null)
        {
            testStatusLabel.Text = _isTestRunning ? "状态: 正在运行" : "状态: 已停止"; // 更新状态标签文本
            testStatusLabel.ForeColor = _isTestRunning ? Color.Green : Color.Red; // 更新状态标签颜色
        }
    }

    /// <summary>
    /// 安全更新测试UI状态
    /// </summary>
    /// <param name="isRunning">测试是否正在运行</param>
    private void SafeUpdateTestUI(bool isRunning)
    {
        // 如果窗体正在释放或已释放，返回
        if (_isDisposing || IsDisposed)
            return;

        try
        {
            // 如果需要在UI线程中调用，使用BeginInvoke避免阻塞，并增加异常处理
            if (InvokeRequired)
            {
                BeginInvoke(
                    new Action(() =>
                    {
                        try
                        {
                            SafeUpdateTestUI(isRunning); // 在UI线程中更新UI状态
                        }
                        catch (Exception ex)
                        {
                            // 在UI线程中的异常处理
                            SafeAppendLog($"UI线程中更新测试UI失败: {ex.Message}", Color.Red);
                        }
                    })
                );
                return;
            }

            // 检查和更新开始按钮
            if (
                startTestButton != null
                && !startTestButton.IsDisposed
                && startTestButton.IsHandleCreated
            )
                startTestButton.Enabled = !isRunning; // 根据测试状态更新开始按钮可用性

            // 检查和更新停止按钮
            if (
                stopTestButton != null
                && !stopTestButton.IsDisposed
                && stopTestButton.IsHandleCreated
            )
                stopTestButton.Enabled = isRunning; // 根据测试状态更新停止按钮可用性

            // 检查和更新状态标签
            if (
                testStatusLabel != null
                && !testStatusLabel.IsDisposed
                && testStatusLabel.IsHandleCreated
            )
            {
                testStatusLabel.Text = isRunning ? "状态: 正在运行" : "状态: 已停止"; // 更新状态标签文本
                testStatusLabel.ForeColor = isRunning ? Color.Green : Color.Red; // 更新状态标签颜色
            }
        }
        catch (ObjectDisposedException)
        {
            // 控件已释放，忽略此异常
        }
        catch (InvalidOperationException)
        {
            // 控件可能已释放或正在释放，忽略此异常
        }
        catch (Exception ex)
        {
            SafeAppendLog($"更新测试UI失败: {ex.Message}", Color.Red); // 记录更新失败日志
        }
    }

    /// <summary>
    /// 异步运行测试任务
    /// </summary>
    /// <param name="cancellationToken">取消令牌</param>
    private async Task RunTestAsync(CancellationToken cancellationToken)
    {
        SafeAppendLog("进入RunTestAsync方法", Color.Cyan); // 记录进入方法日志

        try
        {
            var testDurationMinutes = (double)(testDuration?.Value ?? 60); // 获取测试持续时间（分钟）
            var endTime = _testStartTime.AddMinutes(testDurationMinutes); // 计算测试结束时间
            SafeAppendLog($"测试将运行到: {endTime:HH:mm:ss}", Color.Cyan); // 记录测试结束时间

            while (
                _isTestRunning
                && DateTime.Now < endTime
                && !cancellationToken.IsCancellationRequested
            )
            {
                try
                {
                    // 检查取消状态
                    cancellationToken.ThrowIfCancellationRequested();

                    // 发送测试命令
                    await SendTestCommandAsync(cancellationToken);

                    // 检查超时命令
                    await CheckTimeoutCommandsAsync();

                    // 随机间隔等待
                    var minInterval = (int)(testIntervalMin?.Value ?? 100); // 获取最小间隔
                    var maxInterval = (int)(testIntervalMax?.Value ?? 500); // 获取最大间隔
                    var interval = _random.Next(minInterval, maxInterval + 1); // 生成随机间隔

                    await Task.Delay(interval, cancellationToken); // 延迟等待
                }
                catch (OperationCanceledException)
                {
                    SafeAppendLog("测试循环被取消", Color.Orange); // 记录取消日志
                    break;
                }
                catch (Exception ex)
                {
                    SafeAppendLog($"测试循环异常: {ex.Message}", Color.Red); // 记录异常日志

                    // 在异常情况下等待一秒，但要检查取消状态
                    try
                    {
                        await Task.Delay(1000, cancellationToken); // 延迟等待
                    }
                    catch (OperationCanceledException)
                    {
                        SafeAppendLog("在异常处理等待期间被取消", Color.Orange); // 记录取消日志
                        break;
                    }
                }
            }

            // 检查结束原因
            if (cancellationToken.IsCancellationRequested)
            {
                SafeAppendLog("测试因取消而结束", Color.Orange); // 记录取消结束日志
            }
            else if (DateTime.Now >= endTime)
            {
                SafeAppendLog("测试因达到时间限制而结束", Color.Green); // 记录时间结束日志
            }
            else if (!_isTestRunning)
            {
                SafeAppendLog("测试因手动停止而结束", Color.Orange); // 记录手动结束日志
            }
        }
        catch (OperationCanceledException)
        {
            SafeAppendTestLog("测试被取消", Color.Orange); // 记录取消日志
        }
        catch (Exception ex)
        {
            SafeAppendTestLog($"测试任务异常: {ex.Message}", Color.Red); // 记录任务异常日志
            SafeAppendLog($"测试任务详细异常: {ex}", Color.Red); // 记录详细异常日志
        }
        finally
        {
            SafeAppendLog("测试任务进入finally块", Color.Gray); // 记录进入finally块日志

            // 确保测试状态被正确设置
            if (_isTestRunning)
            {
                SafeAppendLog("在finally中调用StopTest", Color.Gray); // 记录调用停止测试日志
                StopTest();
            }

            SafeAppendLog("RunTestAsync方法结束", Color.Gray); // 记录方法结束日志
        }
    }

    /// <summary>
    /// 异步发送测试命令
    /// </summary>
    /// <param name="cancellationToken">取消令牌</param>
    private async Task SendTestCommandAsync(CancellationToken cancellationToken)
    {
        string portName = null;

        // 确保在UI线程中访问ComboBox
        if (InvokeRequired)
        {
            portName = (string)Invoke(
                new Func<string>(() =>
                {
                    // 检查测试是否正在运行、通讯管理器是否为null或串口ComboBox是否为空
                    if (
                        !_isTestRunning
                        || _communicationManager == null
                        || serialPortComboBox?.SelectedItem == null
                    )
                        return null;
                    return serialPortComboBox.SelectedItem.ToString()!; // 获取串口号
                })
            );
        }
        else
        {
            if (
                !_isTestRunning
                || _communicationManager == null
                || serialPortComboBox?.SelectedItem == null
            )
                return; // 如果测试未运行或通讯管理器为null或串口ComboBox为空，返回

            portName = serialPortComboBox.SelectedItem.ToString()!; // 获取串口号
        }

        if (portName == null)
            return; // 如果串口号为空，返回

        try
        {
            // 获取被勾选的命令列表
            var selectedCommands = _commandItems.Where(c => c.IsSelected).ToList();
            if (selectedCommands.Count == 0)
                return; // 如果没有勾选的命令，返回

            // 选择命令（轮询模式）
            var commandItem = selectedCommands[_commandIndex % selectedCommands.Count]; // 获取当前命令项
            var command = commandItem.Command; // 获取命令字符串
            _commandIndex++; // 增加命令索引
            // 使用ModbusAnalysisHelper解析
            var bytes = ParseHexString(command); // 解析命令为字节数组

            if (bytes == null)
            {
                SafeAppendLog($"解析测试命令失败: {command}", Color.Red); // 记录解析失败日志
                return;
            }

            int currentTestId;
            lock (_testLock)
            {
                _testCount++; // 增加总测试次数
                currentTestId = _testCount; // 设置当前测试ID
            }

            var sendTime = DateTime.Now; // 记录发送时间
            var requestData = command;
            var requestBytes = bytes;
            //需要发送请求并等待响应
            var response = await SendRequestAndWaitForResponse(
                portName,
                requestBytes,
                requestData,
                commandItem.Description
            );
            if (response.Success)
            {
                var timestamp = sendTime.ToString("HH:mm:ss.fff"); // 格式化时间戳
                SafeAppendTestLog($"[{timestamp}] 第{currentTestId}次发送: {command}", Color.Cyan); // 记录发送日志
            }
            else
            {
                _pendingCommands.TryRemove(currentTestId, out _); // 移除待响应命令
                lock (_testLock)
                {
                    _testFailureCount++; // 增加失败次数
                }
                SafeAppendTestLog($"第{currentTestId}次发送失败: {command}", Color.Red); // 记录发送失败日志
            }

            // 在UI线程中更新统计
            if (InvokeRequired)
            {
                Invoke(new Action(UpdateTestStats)); // 在UI线程中更新测试统计
            }
            else
            {
                UpdateTestStats(); // 更新测试统计
            }
        }
        catch (Exception ex)
        {
            SafeAppendLog($"发送测试命令异常: {ex.Message}", Color.Red); // 记录发送异常日志
        }
    }

    /// <summary>
    /// 检查超时命令
    /// </summary>
    private async Task CheckTimeoutCommandsAsync()
    {
        var timeoutMs = 1000; // 设置超时时间为1秒
        var now = DateTime.Now; // 获取当前时间
        var timeoutCommands = new List<int>(); // 创建超时命令列表

        foreach (var kvp in _pendingCommands)
        {
            if ((now - kvp.Value).TotalMilliseconds > timeoutMs)
            {
                timeoutCommands.Add(kvp.Key); // 将超时命令ID添加到列表
            }
        }

        foreach (var commandId in timeoutCommands)
        {
            if (_pendingCommands.TryRemove(commandId, out var sendTime))
            {
                lock (_testLock)
                {
                    _testFailureCount++; // 增加失败次数
                }
                var waitTime = now - sendTime; // 计算等待时间
                AppendTestLog(
                    $"[超时] 第{commandId}次发送无响应 - 等待时间: {waitTime.TotalMilliseconds:F0}ms", // 格式化超时日志
                    Color.Red
                ); // 修复缺少的右括号
            }
        }
    }

    /// <summary>
    /// 验证响应是否有效
    /// </summary>
    /// <param name="requestData">请求数据</param>
    /// <param name="responseData">响应数据</param>
    /// <returns>响应是否有效</returns>
    private bool IsResponseValid(byte[] requestData, byte[] responseData)
    {
        try
        {
            // 检查响应数据是否存在且不为空
            if (responseData == null || responseData.Length == 0)
            {
                AppendLog("验证响应有效性: 响应数据为空", Color.Orange);
                return false;
            }

            // 检查响应数据长度是否足够（至少包含设备地址、功能码和CRC）
            if (responseData.Length < 4)
            {
                AppendLog(
                    $"验证响应有效性: 响应数据长度不足，当前长度: {responseData.Length}",
                    Color.Orange
                );
                return false;
            }

            // 检查设备地址是否匹配
            if (
                requestData.Length > 0
                && responseData.Length > 0
                && requestData[0] != responseData[0]
            )
            {
                AppendLog(
                    $"验证响应有效性: 设备地址不匹配，请求地址: 0x{requestData[0]:X2}, 响应地址: 0x{responseData[0]:X2}",
                    Color.Orange
                );
                return false;
            }

            // 检查功能码是否匹配或为错误响应
            if (requestData.Length > 1 && responseData.Length > 1)
            {
                var requestFunctionCode = requestData[1];
                var responseFunctionCode = responseData[1];

                // 检查是否为错误响应（功能码最高位为1）
                bool isErrorResponse = (responseFunctionCode & 0x80) != 0;

                // 如果是错误响应，记录错误信息
                if (isErrorResponse)
                {
                    var originalFunctionCode = responseFunctionCode & 0x7F;
                    if (originalFunctionCode == requestFunctionCode)
                    {
                        AppendLog(
                            $"验证响应有效性: 收到功能码 {requestFunctionCode:X2} 的错误响应",
                            Color.Orange
                        );
                        return true; // 错误响应也是有效的响应
                    }
                    else
                    {
                        AppendLog(
                            $"验证响应有效性: 错误响应功能码不匹配，请求功能码: 0x{requestFunctionCode:X2}, 响应功能码: 0x{responseFunctionCode:X2}",
                            Color.Orange
                        );
                        return false;
                    }
                }

                // 如果响应功能码与请求功能码不相同
                if (responseFunctionCode != requestFunctionCode)
                {
                    AppendLog(
                        $"验证响应有效性: 功能码不匹配，请求功能码: 0x{requestFunctionCode:X2}, 响应功能码: 0x{responseFunctionCode:X2}",
                        Color.Orange
                    );
                    return false;
                }

                // 根据不同的功能码进行特定验证
                switch (requestFunctionCode)
                {
                    // 读取功能码（03, 04）
                    case 0x03:
                    case 0x04:
                        if (responseData.Length >= 3)
                        {
                            // 检查字节数字段是否合理
                            var byteCount = responseData[2];
                            // 响应格式: [设备地址] [功能码] [字节数] [数据...] [CRC低] [CRC高]
                            // 数据长度应为: 3(设备地址+功能码+字节数) + 字节数 + 2(CRC)
                            if (responseData.Length == 3 + (byteCount) + 2)
                            {
                                AppendLog(
                                    $"验证响应有效性: 读取功能码 {requestFunctionCode:X2} 响应验证通过",
                                    Color.Green
                                );
                                return true;
                            }
                            else
                            {
                                AppendLog(
                                    $"验证响应有效性: 读取功能码 {requestFunctionCode:X2} 响应长度不正确，期望: {3 + byteCount + 2}, 实际: {responseData.Length}",
                                    Color.Orange
                                );
                                return false;
                            }
                        }
                        break;

                    // 写单个寄存器功能码（06）
                    case 0x06:
                        // 写单个寄存器响应通常包含设备地址、功能码、寄存器地址、数据值和CRC（共8字节）
                        if (responseData.Length == 8)
                        {
                            AppendLog(
                                $"验证响应有效性: 写单个寄存器功能码 06 响应验证通过",
                                Color.Green
                            );
                            return true;
                        }
                        else
                        {
                            AppendLog(
                                $"验证响应有效性: 写单个寄存器功能码 06 响应长度不正确，期望: 8, 实际: {responseData.Length}",
                                Color.Orange
                            );
                            return false;
                        }

                    // 写多个寄存器功能码（10）
                    case 0x10:
                        // 写多个寄存器响应通常包含设备地址、功能码、寄存器地址、寄存器数量和CRC（共8字节）
                        if (responseData.Length == 8)
                        {
                            AppendLog(
                                $"验证响应有效性: 写多个寄存器功能码 10 响应验证通过",
                                Color.Green
                            );
                            return true;
                        }
                        else
                        {
                            AppendLog(
                                $"验证响应有效性: 写多个寄存器功能码 10 响应长度不正确，期望: 8, 实际: {responseData.Length}",
                                Color.Orange
                            );
                            return false;
                        }

                    // 对于其他功能码，进行基本验证
                    default:
                        AppendLog(
                            $"验证响应有效性: 功能码 {requestFunctionCode:X2} 响应验证通过（基本验证）",
                            Color.Green
                        );
                        return true;
                }
            }

            AppendLog("验证响应有效性: 请求或响应数据不完整", Color.Orange);
            return false;
        }
        catch (Exception ex)
        {
            AppendLog($"验证响应有效性时出错: {ex.Message}", Color.Red);
            return false;
        }
    }
}
